<template>
  <div>
    <div>
      <h2>参考博客</h2>
      <ul>
        <li>https://gojs.net.cn/learn/index.html</li>
        <li>https://blog.csdn.net/Lnbd_/article/details/123798632</li>
        <li>https://blog.csdn.net/zhengyinling/article/details/109489903</li>
        <li>https://www.zhihu.com/people/xie-chen-hua-46/posts</li>
        <li>https://www.evget.com/doclib/s/79/13615</li>
      </ul>
      <p>如果你还没有接触过GoJS， 并对它有兴趣的话，推荐学习路线为&nbsp;
        <a href="https://gojs.net/latest/learn/index.html" target="_blank">Learn</a>&nbsp;-&gt;&nbsp;
        <a href="https://gojs.net/latest/intro/index.html" target="_blank">Intro</a>&nbsp;-&gt;&nbsp;
        <a href="https://gojs.net/latest/samples/index.html" target="_blank">Samples</a>&nbsp;-&gt;&nbsp;
        <a href="https://gojs.net/latest/api/index.html" target="_blank">API</a>
      </p>
    </div>
    <div>
      <h2>技术要点</h2>
      <ul>
        <li>1.定制节点的样式</li>
        <li>2.curd节点关系，支持键盘快捷键操作</li>
        <li>3.序列化与反序列化</li>
        <li>4.对节点支持右键菜单</li>
        <li>5.拖拽生成节点</li>
      </ul>

      基于这个还可以做工作流
      https://gojs.net.cn/samples/draggableLink.html
    </div>
    <div class="demoArea">
      <div>
        <h2>快速上手</h2>
        <!-- 可以通过设置style来设置图标的宽高 -->
        <div ref="myDiagram1" id="myDiagram1" style="border: solid 1px black; width:400px; height:200px"></div>
      </div>

      <div>
        <h2>定制节点样式</h2>
        <!-- 可以通过设置style来设置图标的宽高 -->
        <div ref="myDiagram2" id="myDiagram2" style="border: solid 1px black; width:400px; height:200px"></div>
      </div>

      <div>
        <h2>实现关联图的雏形1</h2>
        <!-- 可以通过设置style来设置图标的宽高 -->
        <div ref="myDiagram3" id="myDiagram3" style="border: solid 1px black; width:400px; height:200px"></div>
      </div>
      <div>
        <h2>实现关联图的雏形2<br />连接线上加label，怎么调整label文字的位置？</h2>
        <!-- 可以通过设置style来设置图标的宽高 -->
        <div ref="myDiagram99" id="myDiagram99" style="border: solid 1px black; width:400px; height:200px"></div>
      </div>

      <div>
        <h2>节点分组</h2>
        <div></div>
        <!-- 可以通过设置style来设置图标的宽高 -->
        <div ref="myDiagram4" id="myDiagram4" style="border: solid 1px black; width:400px; height:200px"></div>
      </div>

      <div>
        <h2><a href="https://gojs.net.cn/samples/draggableLink.html" target="_blank">工作流</a></h2>
        <div></div>
        <!-- 可以通过设置style来设置图标的宽高 -->
        <div ref="myDiagram5" id="myDiagram5" style="border: solid 1px black; width:400px; height:200px"></div>
      </div>

      <div>
        <h2><a href="https://gojs.net.cn/samples/customContextMenu.html" target="_blank">右键菜单</a></h2>
        <div></div>
        <!-- 可以通过设置style来设置图标的宽高 -->
        <div ref="myDiagram6" id="myDiagram6" style="border: solid 1px black; width:400px; height:200px"></div>
      </div>
    </div>

    <!-- @contextmenu.prevent：对右键菜单右击是无效的 -->
    <ul id="contextMenu" class="ctxmenu" @contextmenu.prevent="()=>{}">
      <li id="cut" class="menu-item" @click="cxcommand($event)">Cut</li>
      <li id="copy" class="menu-item" @click="cxcommand($event)">Copy</li>
      <li id="paste" class="menu-item" @click="cxcommand($event)">Paste</li>
      <li id="delete" class="menu-item" @click="cxcommand($event)">Delete</li>
      <li id="color" class="menu-item">Color
        <ul class="ctxmenu">
          <li class="menu-item" style="background-color: #f38181;" @click="cxcommand($event, 'color')">Red</li>
          <li class="menu-item" style="background-color: #eaffd0;" @click="cxcommand($event, 'color')">Green</li>
          <li class="menu-item" style="background-color: #95e1d3;" @click="cxcommand($event, 'color')">Blue</li>
          <li class="menu-item" style="background-color: #fce38a;" @click="cxcommand($event, 'color')">Yellow</li>
        </ul>
      </li>
    </ul>
  </div>
</template>

<script>
import go from 'gojs'

export default {
  components: {
  },
  mounted () {
    for (let i = 1; i < 100; i++) {
      if (this["initMyDiagram" + i]) {
        this["initMyDiagram" + i](`myDiagram${i}`);
      }
    }
  },
  data () {
    return {
      data1: {
        'rootId': 'N1',
        'nodes': [{
          "key": "N1",
          "text": "侯亮平",
          "color": "#ec6941",
          "borderColor": "#ff875e",
          "borderWidth": 3,
          "data": {
            "isGoodMan": true,
            "sexType": "男"
          },
          "innerHTML": "https://dss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=2308340537,462224207&fm=58&app=83&f=JPEG?w=250&h=250&s=EC708F46DA96B89CB69D5DDA0300D014"
        },
        {
          "key": "N2",
          "text": "李达康",
          "color": "#ec6941",
          "borderColor": "#ff875e",
          "borderWidth": 3,
          "data": {
            "isGoodMan": true,
            "sexType": "男"
          },
          "innerHTML": "https://dss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=2677153550,2207805387&fm=58&app=83&f=JPEG?w=250&h=250&s=249039DDC2D153D411A851360300C062"
        },
        {
          "key": "N3",
          "text": "祁同伟",
          "color": "rgba(0, 206, 209, 1)",
          "borderColor": "#6cc0ff",
          "borderWidth": 3,
          "data": {
            "isGoodMan": false,
            "sexType": "男"
          },
          "innerHTML": "https://dss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=1725297532,1915921796&fm=58&app=83&f=JPEG?w=250&h=250&s=FE8EA444A60759554DAC1DBB03000092"
        },
        {
          "key": "N4",
          "text": "陈岩石",
          "color": "#ec6941",
          "borderColor": "#ff875e",
          "borderWidth": 3,
          "data": {
            "isGoodMan": true,
            "sexType": "男"
          },
          "innerHTML": "https://dss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=2025797948,1615296290&fm=58&app=83&f=JPEG?w=250&h=250&s=B5B04C331F32739C4604F9F503007021"
        }],
        'links': [{
          "from": "N2",
          "to": "N1",
          "text": "师生",
          "color": "#d2c0a5",
          "fontColor": "#d2c0a5",
          "data": {
            "type": "师生"
          }
        },
        {
          "from": "N4",
          "to": "N3",
          "text": "师生",
          "color": "#d2c0a5",
          "fontColor": "#d2c0a5",
          "data": {
            "type": "师生"
          }
        },
        {
          "from": "N3",
          "to": "N3",
          "text": "上下级",
          "color": "#d2c0a5",
          "fontColor": "#d2c0a5",
          "data": {
            "type": "上下级"
          }
        }]
      },
    }
  },
  methods: {
    initMyDiagram1 () {
      let diagram = new go.Diagram("myDiagram1");
      diagram.model = new go.GraphLinksModel(
        // 节点数据
        [
          { key: "Hello" },
          { key: "World!" }
        ],
        // 关系
        [{ from: "Hello", to: "World!" }]
      );
    },
    initMyDiagram2 () {
      let $ = go.GraphObject.make; // 为了简化绘图时new对象的写法，我们直接将GoJS的构造函数赋值给一个简单的对象
      let diagram = $(go.Diagram, "myDiagram2");
      diagram.nodeTemplate =
        $(go.Node, "Auto",
          $(go.Shape,
            { figure: "RoundedRectangle", fill: "white" },
            new go.Binding("fill", "color")),
          $(go.TextBlock,
            { margin: 5 },
            new go.Binding("text", "key"))
        );

      let nodeDataArray = [
        { key: "Alpha", color: "lightblue" },
        { key: "Beta", color: "pink" }
      ];
      let linkDataArray = [
        { from: "Alpha", to: "Beta" }
      ];
      diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
    },
    initMyDiagram3 () {
      let $ = go.GraphObject.make; // 为了简化绘图时new对象的写法，我们直接将GoJS的构造函数赋值给一个简单的对象
      let diagram = $(go.Diagram, "myDiagram3");
      diagram.nodeTemplate =
        new go.Node(
          // 垂直布局，上面图片，下面文字
          "Vertical",
          // 配置
          {
            //background: "#44CCFF" // 节点的背景颜色
          })
          .add(
            new go.Picture(
              // 配置
              {
                margin: 10,
                width: 50,
                height: 50,
                background: "red"
              }
            ).bind("source", "innerHTML") // 图片绑定modelData的source字段
          )
          .add(
            new go.TextBlock(
              "Default Text",  // 默认文字
              // 配置
              {
                margin: 12,
                stroke: "black", // 字体颜色
                font: "bold 16px sans-serif"
              })
              .bind("text", "text") // 文字绑定modelData的name字段
          );

      diagram.model = new go.GraphLinksModel(this.data1.nodes, this.data1.links);
    },
    initMyDiagram99 () {
      let $ = go.GraphObject.make; // 为了简化绘图时new对象的写法，我们直接将GoJS的构造函数赋值给一个简单的对象
      let diagram = $(go.Diagram, "myDiagram99");
      diagram.nodeTemplate =
        new go.Node(
          // 垂直布局，上面图片，下面文字
          "Vertical",
          // 配置
          {
            //background: "#44CCFF" // 节点的背景颜色
          })
          .add(
            new go.Picture(
              // 配置
              {
                margin: 10,
                width: 50,
                height: 50,
                background: "red"
              }
            ).bind("source", "innerHTML") // 图片绑定modelData的source字段
          )
          .add(
            new go.TextBlock(
              "Default Text",  // 默认文字
              // 配置
              {
                margin: 12,
                stroke: "black", // 字体颜色
                font: "bold 16px sans-serif"
              })
              .bind("text", "text") // 文字绑定modelData的name字段
          );

      diagram.linkTemplate =
        $(go.Link,
          $(go.Shape),                           // this is the link shape (the line)，形状
          $(go.Shape, { toArrow: "Standard" }),  // this is an arrowhead，这是一个箭头
          $(go.TextBlock,                        // this is a Link label，连接线的label
            new go.Binding("text", "text"))
        );

      diagram.model = new go.GraphLinksModel(this.data1.nodes, this.data1.links);

    },
    initMyDiagram4 () {
      let $ = go.GraphObject.make; // 为了简化绘图时new对象的写法，我们直接将GoJS的构造函数赋值给一个简单的对象
      let diagram = $(go.Diagram, "myDiagram4");
      let model = {};
      model.nodeDataArray = [
        { key: "Alpha" },
        { key: "Beta" }
      ];
      model.linkDataArray = [
        { from: "Alpha", to: "Beta" }
      ];

      // 可以对节点进行分组
      model.nodeDataArray = [
        { key: "Group1", isGroup: true },
        { key: "Alpha", group: "Group1" },
        { key: "Beta", group: "Group1" },
        { key: "Gamma" }
      ];
      model.linkDataArray = [
        { from: "Alpha", to: "Beta" },
        { from: "Group1", to: "Gamma" }
      ];
      diagram.model = new go.GraphLinksModel(model.nodeDataArray, model.linkDataArray);
    },
    initMyDiagram5 () { },
    initMyDiagram6 (idSelector = "myDiagram6") {
      var $ = go.GraphObject.make;  // for conciseness in defining templates
      let myDiagram = $(go.Diagram, idSelector);
      this.myDiagram6 = myDiagram;
      // 初始化右键菜单
      let myContextMenu = this.initContextMenu(myDiagram);

      // define a simple Node template (but use the default Link template)
      myDiagram.nodeTemplate =
        $(go.Node, "Auto", { contextMenu: myContextMenu },
          $(go.Shape, "RoundedRectangle",
            new go.Binding("fill", "color")),
          $(go.TextBlock,
            { margin: 3 },
            new go.Binding("text", "key"))
        );
      // create the model data that will be represented by Nodes and Links
      myDiagram.model = new go.GraphLinksModel(
        [
          { key: "Alpha", color: "#f38181" },
          { key: "Beta", color: "#eaffd0" },
          { key: "Gamma", color: "#95e1d3" },
          { key: "Delta", color: "#fce38a" }
        ],
        [
          { from: "Alpha", to: "Beta" },
          { from: "Alpha", to: "Gamma" },
          { from: "Beta", to: "Beta" },
          { from: "Gamma", to: "Delta" },
          { from: "Delta", to: "Alpha" }
        ]);
    },
    initContextMenu (myDiagram) {
      var $ = go.GraphObject.make;
      // 右键菜单。HTMLInfo用于显示和隐藏自定义HTML页面元素，如右键菜单、工具提示等。
      var myContextMenu = $(go.HTMLInfo, {
        show: showContextMenu,
        hide: hideContextMenu
      });
      myDiagram.contextMenu = myContextMenu;
      // This is the actual HTML context menu:
      var cxElement = document.getElementById("contextMenu");

      function doHideContextMenu () {
        if (myDiagram.currentTool instanceof go.ContextMenuTool) {
          myDiagram.currentTool.doCancel();
        }
      }

      function showContextMenu (obj, diagram, tool) {
        var hasMenuItem = false; // 是否有要显示的右键菜单
        function maybeShowItem (element, pred) {
          if (pred) {
            element.style.display = "block";
            hasMenuItem = true;
          } else {
            element.style.display = "none";
          }
        }

        maybeShowItem(document.getElementById("cut"), diagram.commandHandler.canCutSelection());
        maybeShowItem(document.getElementById("copy"), diagram.commandHandler.canCopySelection());
        maybeShowItem(document.getElementById("paste"), diagram.commandHandler.canPasteSelection(diagram.toolManager.contextMenuTool.mouseDownPoint));
        maybeShowItem(document.getElementById("delete"), diagram.commandHandler.canDeleteSelection());
        maybeShowItem(document.getElementById("color"), obj !== null);
        // Now show the whole context menu element
        if (hasMenuItem) {
          cxElement.classList.add("show-menu");
          let container = document.getElementById("myDiagram6");

          // 修改右键菜单的定位
          var mousePt = diagram.lastInput.viewPoint;
          cxElement.style.left = mousePt.x + container.offsetLeft + "px";
          cxElement.style.top = mousePt.y + + container.offsetTop + "px";
        }
        window.addEventListener("click", doHideContextMenu, true);
      }

      function hideContextMenu () {
        cxElement.classList.remove("show-menu");
        window.removeEventListener("click", doHideContextMenu, true);
      }

      return myContextMenu;
    },
    // This is the general menu command handler, parameterized by the name of the command.
    cxcommand (event, val) {
      if (!val) {
        val = event.currentTarget.id;
      }
      var diagram = this.myDiagram6;
      switch (val) {
        // diagram.commandHandler里内置了很多方法，可以直接调用
        case "cut": diagram.commandHandler.cutSelection(); break;
        case "copy": diagram.commandHandler.copySelection(); break;
        case "paste": diagram.commandHandler.pasteSelection(diagram.toolManager.contextMenuTool.mouseDownPoint); break;
        case "delete": diagram.commandHandler.deleteSelection(); break;
        // 自定义方法
        case "color": {
          var color = window.getComputedStyle(event.target)['background-color'];

          // A custom command, for changing the color of the selected node(s).
          let changeColor = (diagram, color) => {
            // Always make changes in a transaction, except when initializing the diagram.
            diagram.startTransaction("change color");
            diagram.selection.each(function (node) {
              if (node instanceof go.Node) {  // ignore any selected Links and simple Parts
                // Examine and modify the data, not the Node directly.
                var data = node.data;
                // Call setDataProperty to support undo/redo as well as
                // automatically evaluating any relevant bindings.
                diagram.model.setDataProperty(data, "color", color);
              }
            });
            diagram.commitTransaction("change color");
          };
          changeColor(diagram, color); break;
        }
      }
      diagram.currentTool.stopTool();
    }
  }

}
</script>

<style lang="less" scoped>
.demoArea {
  display: flex;
  flex-wrap: wrap;
}

#contextMenu {
  position: absolute;
  opacity: 1;
  display: none;
  z-index: 10;
  background: whitesmoke;
}
#contextMenu.show-menu {
  display: block;
}
</style>